package com.net.reflection;

import com.net.annotation.FieldMeta;
import com.net.annotation.Mean;
import com.net.domain.Apple;
import com.net.domain.BaseEntity;
import com.net.domain.User;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * Created by zhang yufei on 2017/12/2.
 */
@Repository
public class ReflectionUtil {

    public Class getClass(Object o) {
        return o.getClass();
    }

    public String getClassName(Object o) {
        return o.getClass().getName();
    }

    public Annotation[] getAnnotation(Object o) throws NoSuchMethodException {
        return o.getClass().getAnnotations();
    }

    public void getAnnotationSystem(Object o) throws NoSuchMethodException {
        AccessibleObject sampleMethod = o.getClass().getMethod("getId");
        Annotation annotation = sampleMethod.getAnnotation(Mean.class);
        if (annotation instanceof Mean) {
            Mean customAnnotation = (Mean) annotation;
            System.out.println("mean: " + customAnnotation.mean());
        }
    }

    public static  <T> T mapToEntity(Map<String, Object> map, Class<T> c) {
        try {
            T model = c.newInstance();
            Field[] field = model.getClass().getDeclaredFields();
            for (int j = 0; j < field.length; j++) { // 遍历所有属性
                String nameSmall = field[j].getName(); // 获取属性的名字
                String name = nameSmall.substring(0, 1).toUpperCase() + nameSmall.substring(1); // 将属性的首字符大写，方便构造get，set方法
                String type = field[j].getGenericType().toString(); // 获取属性的类型
                if (type.equals("class java.lang.String")) { // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = model.getClass().getMethod("get" + name);
                    String value = (String) m.invoke(model); // 调用getter方法获取属性值
                    if (value == null) {
                        m = model.getClass().getMethod("set" + name, String.class);
                        if (map.get(nameSmall) != null) {
                            m.invoke(model, map.get(nameSmall).toString());
                        }
                    }
                }
                if (type.equals("class java.lang.Integer")) {
                    Method m = model.getClass().getMethod("get" + name);
                    Integer value = (Integer) m.invoke(model);
                    if (value == null) {
                        m = model.getClass().getMethod("set" + name, Integer.class);
                        if (map.get(nameSmall) != null) {
                            m.invoke(model, Integer.parseInt(map.get(nameSmall).toString()));
                        }
                    }
                }
                if (type.equals("class java.lang.Boolean")) {
                    Method m = model.getClass().getMethod("get" + name);
                    Boolean value = (Boolean) m.invoke(model);
                    if (value == null) {
                        m = model.getClass().getMethod("set" + name, Boolean.class);
                        if (map.get(nameSmall) != null) {
                            m.invoke(model, map.get(nameSmall).toString());
                        }
                    }
                }
                if (type.equals("class java.util.Date")) {
                    Method m = model.getClass().getMethod("get" + name);
                    Date value = (Date) m.invoke(model);
                    if (value == null) {
                        m = model.getClass().getMethod("set" + name, Date.class);
                        m.invoke(model, new Date());
                    }
                }
                // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断
            }
            return model;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public <T> T mapToEntityAnn(Map<String, Object> map, Class<T> c) {
        try {
            T model = c.newInstance();
            Field[] field = model.getClass().getDeclaredFields();
            for (int j = 0; j < field.length; j++) { // 遍历所有属性
                Annotation annotation = field[j].getAnnotation(Mean.class);
                if (annotation instanceof Mean) {
                    Mean customAnnotation = (Mean) annotation;
                    String colum = customAnnotation.colum();
                    String nameSmall = field[j].getName(); // 获取属性的名字
                    String name = nameSmall.substring(0, 1).toUpperCase() + nameSmall.substring(1); // 将属性的首字符大写，方便构造get，set方法
                    String type = field[j].getGenericType().toString(); // 获取属性的类型
                    if (type.equals("class java.lang.String")) { // 如果type是类类型，则前面包含"class "，后面跟类名
                        Method m = model.getClass().getMethod("get" + name);
                        String value = (String) m.invoke(model); // 调用getter方法获取属性值
                        if (value == null) {
                            m = model.getClass().getMethod("set" + name, String.class);
                            if (map.get(nameSmall) != null) {
                                m.invoke(model, map.get(colum).toString());
                            }
                        }
                    }
                    if (type.equals("class java.lang.Integer")) {
                        Method m = model.getClass().getMethod("get" + name);
                        Integer value = (Integer) m.invoke(model);
                        if (value == null) {
                            m = model.getClass().getMethod("set" + name, Integer.class);
                            if (map.get(nameSmall) != null) {
                                m.invoke(model, Integer.parseInt(map.get(colum).toString()));
                            }
                        }
                    }
                    if (type.equals("class java.lang.Boolean")) {
                        Method m = model.getClass().getMethod("get" + name);
                        Boolean value = (Boolean) m.invoke(model);
                        if (value == null) {
                            m = model.getClass().getMethod("set" + name, Boolean.class);
                            if (map.get(nameSmall) != null) {
                                m.invoke(model, map.get(colum).toString());
                            }
                        }
                    }
                    if (type.equals("class java.util.Date")) {
                        Method m = model.getClass().getMethod("get" + name);
                        Date value = (Date) m.invoke(model);
                        if (value == null) {
                            m = model.getClass().getMethod("set" + name, Date.class);
                            m.invoke(model, map.get(colum).toString());
                        }
                    }
                    // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断
                }
            }
            return model;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Test
    public void test() {
        Apple apple = new Apple();
        Class clazz = this.getClass(apple);

        String name = this.getClassName(apple);

        User user = new User();
        try {
            this.getAnnotation(user);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}
